ReliableSocketRequestEmitter.createEmitPack   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 9
dl 0
loc 13
rs 9.95
c 0
b 0
f 0
1
import { InQueueType } from '../enums/in-queue-type';
2
import { IReliableSocketEmitOptions } from '../interfaces/i-reliable-socket-emit-options';
3
import { IReliableSocketRequest } from '../interfaces/i-reliable-socket-request';
4
import { IReliableSocketRequestPack } from '../interfaces/i-reliable-socket-request-pack';
5
import { IReliableSocketRequestQueues } from '../interfaces/i-reliable-socket-request-queues';
6
import { ISocketEmitter } from '../interfaces/i-socket-emitter';
7
8
export class ReliableSocketRequestEmitter {
9
    private defaultEmitOptions = {
10
        inQueueType: InQueueType.anytime,
11
        maxTryCount: 10,
12
        queueName: 'default',
13
        retryTime: 1000,
14
    };
15
    private emitQueues: IReliableSocketRequestQueues = {
16
        default: [],
17
    };
18
    private emitRequestCounter = 0;
19
20
    public emit(
21
        socket: ISocketEmitter,
22
        eventName: string,
23
        body: any,
24
        optionsIn: Partial<IReliableSocketEmitOptions> = this
25
            .defaultEmitOptions,
26
    ): Promise<any> {
27
        const options: IReliableSocketEmitOptions = Object.assign(
28
            {},
29
            this.defaultEmitOptions,
30
            optionsIn,
31
        );
32
33
        const socketRequest = {
34
            eventName,
35
            id: this.emitRequestCounter++,
36
            isCompleted: false,
37
            options,
38
            tryCountLeft: options.maxTryCount,
39
            body
40
        } as IReliableSocketRequest;
41
42
        if (this.emitQueues[options.queueName] === undefined) {
43
            this.emitQueues[options.queueName] = [];
44
        }
45
46
        this.emitQueues[options.queueName].push(socketRequest);
47
48
        return this.createEmitPromise(socket, socketRequest, options);
49
    }
50
51
    private removeFromEmitQueue(socketRequest: IReliableSocketRequest) {
52
        this.emitQueues[socketRequest.options.queueName].splice(
53
            this.emitQueues[socketRequest.options.queueName].indexOf(
54
                socketRequest,
55
            ),
56
            1,
57
        );
58
    }
59
60
    private createEmitPromise(
61
        socket: ISocketEmitter,
62
        socketRequest: IReliableSocketRequest,
63
        options: IReliableSocketEmitOptions,
64
    ): Promise<any> {
65
        return new Promise((resolve, reject) => {
66
            socketRequest.isCompleted = false;
67
68
            this.emitRequest(socket, socketRequest, response => {
69
                resolve(response);
70
            }, (err: string) => {
71
                reject(err);
72
            });
73
74
            socketRequest.interval = setInterval(() => {
75
                this.emitRequest(socket, socketRequest, response => {
76
                    resolve(response);
77
                }, (err: string) => {
78
                    reject(err);
79
                });
80
            }, options.retryTime);
81
        });
82
    }
83
84
    /**
85
     * Emit the request in a package and mark as completed if success
86
     */
87
    private emitRequest(
88
        socket: ISocketEmitter,
89
        socketRequest: IReliableSocketRequest,
90
        callback: (response: any) => void,
91
        reject: (msg: string) => void,
92
    ): void {
93
        // socketRequest.options.maxTryCount === 0 means infinite retries
94
        if (socketRequest.tryCountLeft <= 0 && socketRequest.options.maxTryCount !== 0) {
95
            reject('Max try count reached!');
96
            return;
97
        }
98
99
        // Request already completed
100
        if (socketRequest.isCompleted || (socketRequest.tryCountLeft <= 0 && socketRequest.options.maxTryCount !== 0)) {
101
            if (socketRequest.interval) {
102
                clearInterval(socketRequest.interval);
103
            }
104
            return;
105
        }
106
107
108
        if (socket) {
109
            socket.emit(
110
                socketRequest.eventName,
111
                this.createEmitPack(socketRequest),
112
                (response: any) => {
113
                    socketRequest.isCompleted = true;
114
                    this.removeFromEmitQueue(socketRequest);
115
116
                    if (socketRequest.interval) {
117
                        clearInterval(socketRequest.interval);
118
                    }
119
120
                    callback(response);
121
                },
122
            );
123
        } else {
124
            throw Error('No provided socket!');
125
        }
126
    }
127
128
    /**
129
     * Create transfer package with meta information
130
     */
131
    private createEmitPack(
132
        request: IReliableSocketRequest
133
    ): IReliableSocketRequestPack {
134
        return {
135
            body: request.body,
136
            meta: {
137
                id: this.emitRequestCounter,
138
                inQueueType: request.options.inQueueType,
139
                queueName: request.options.queueName,
140
            },
141
        };
142
    }
143
}
144